import 'dart:convert';
import 'dart:isolate';

import 'package:flutter/material.dart';

import 'package:http/http.dart' as http;

/// 深入理解Flutter多线程
/// https://www.jianshu.com/p/54da18ed1a9e
///
/// 深入理解Flutter引擎线程模式
/// https://blog.csdn.net/weixin_38912070/article/details/93857033
///
/// A Dart Isolates example (Actors in Dart)
/// https://alvinalexander.com/dart/dart-isolates-example/
///
/// microtask queue, event queue, microtask queue 中的任务不可以太耗时, 否则会造成卡顿
/// Future 对象就是一个 event, 被 await 标记的是一个 event
///

class IsolatePage extends StatefulWidget {
  final Map<String, dynamic> arguments;
  IsolatePage({Key key, this.arguments}) : super(key: key);

  @override
  _IsolatePageState createState() => _IsolatePageState();
}

class _IsolatePageState extends State<IsolatePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('IsolatePage'),
      ),
      body: ListView(
        children: <Widget>[
          ListTile(
            title: Text('''
Isolates example'''),
            onTap: () {
              isolatesExample();
            },
          ),
          Divider(height: 1.0),
          ListTile(
            title: Text('''
Isolate http load data'''),
            onTap: () {
              final futureData = httpLoadData();
              futureData.then((v) {
                for (Map item in v) {
                  print('title is: ' + item['title']);
                }
              });
            },
          ),
        ],
      ),
    );
  }

// ====================================================================================================
// Isolates example
  Future isolatesExample() async {
    var firstReceivePort = ReceivePort();
    await Isolate.spawn(echo, firstReceivePort.sendPort);
    SendPort echoPort = await firstReceivePort.first;

    //
    var secondReceivePort = ReceivePort();
    echoPort.send(['image', secondReceivePort.sendPort]);
    secondReceivePort.first.then((v) {
      print('main receive msg: $v');
    });

    //
    Future.delayed(Duration(seconds: 2), () {
      var receivePort3 = ReceivePort();
      echoPort.send(['video', receivePort3.sendPort]);
      receivePort3.first.then((v) {
        print('main receive msg: $v');
      });
    });

    //
    var receivePort4 = ReceivePort();
      echoPort.send(['pdf', receivePort4.sendPort]);
      receivePort4.first.then((v) {
        print('main receive msg: $v');
      });
  }

  static echo(SendPort sendPort) async {
    var ourReceivePort = ReceivePort();

    // 当前 ioslate
    // print(Isolate.current.debugName);

    // 阻塞当前 isolate
    // sleep(Duration(seconds: 2));

    sendPort.send(ourReceivePort.sendPort);

    // 单个 send 情况时, msg 可以直接取 first (var msg = await ourReceivePort.first;), 否则使用 for.
    await for (var msg in ourReceivePort) {
      var m0 = msg[0];
      SendPort replyToPort = msg[1];

      print('echo receive msg: $m0');
      Future.delayed(Duration(seconds: 3), () {
        replyToPort.send('$m0 has been written to the file.');
      });
    }
  }

// ====================================================================================================
// Isolate http load data
  Future<List> httpLoadData() async {
    ReceivePort receivePort = ReceivePort();
    print('1');
    await Isolate.spawn(dataLoader, receivePort.sendPort);
    print('2');
    SendPort sendPort = await receivePort.first;
    print('3');

    ReceivePort response = ReceivePort();
    sendPort.send(['https://jsonplaceholder.typicode.com/posts', response.sendPort]);

    List msg = await response.first;
    print('4');

    return msg;
  }

  static dataLoader(SendPort sendPort) async {
    ReceivePort port = ReceivePort();
    sendPort.send(port.sendPort);

    print('5');
    final fir = await port.first;

    String data = fir[0];
    SendPort replyTo = fir[1];

    String dataURL = data;

    print('6');
    http.Response response = await http.get(dataURL);

    final jsonS = json.decode(response.body);

    replyTo.send(jsonS);
  }
}
